﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Input;
using WPFDiagramming.Interfaces;
using System.ComponentModel;
using System.Windows.Documents;

namespace WPFDiagramming.Controls
{
    public abstract class ControlBase : Control, IEvents, INotifyPropertyChanged
    {
        public static readonly RoutedEvent SelectedEvent = EventManager.RegisterRoutedEvent("Selected", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(IEvents));
        public static readonly RoutedEvent DeletedEvent = EventManager.RegisterRoutedEvent("Deleted", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(IEvents));

        public IDesigner Designer { get; set; }

        public ControlBase()
        {
            Selected += OnSelected;

            this.BorderBrush = Brushes.Black;

            this.Focusable = true;
        }

        public event RoutedEventHandler Selected
        {
            add { AddHandler(ControlBase.SelectedEvent, value); }
            remove { RemoveHandler(ControlBase.SelectedEvent, value); }
        }

        public event RoutedEventHandler Deleted
        {
            add { AddHandler(ControlBase.DeletedEvent, value); }
            remove { RemoveHandler(ControlBase.DeletedEvent, value); }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(e.Property.Name));

            this.InvalidateVisual();
        }

        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            this.RaiseEvent(new RoutedEventArgs(ControlBase.SelectedEvent));
        }

        protected abstract void OnSelected(object sender, RoutedEventArgs e);

        public virtual void RemoveAdorners()
        {
            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
            Adorner[] adorners = null;
            if ((adorners = adornerLayer.GetAdorners(this)) != null)
            {
                foreach (var adorner in adorners)
                {
                    adornerLayer.Remove(adorner);
                }
            }
        }

        private Pen pen
        {
            get
            {
                return new Pen()
                        {
                            Brush = this.BorderBrush,
                            Thickness = 2
                        };
            }
        }

        protected abstract Geometry DrawGeometry();

        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);

            drawingContext.DrawGeometry(this.Background, pen, this.DrawGeometry());
        }
    }
}
